package v1

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"
	"gorm.io/gorm"
	"maya-service/bll"
	log "maya-service/collector/logger"
	"maya-service/config"
	"maya-service/model"
	"maya-service/model/po"
	"maya-service/server/web/middleware"
	"maya-service/store/redis"
	"maya-service/utils"
	"maya-service/utils/request"
	"time"
)

var UserRecord = &userRecord{}

func init() {
	RegisterRouter(UserRecord)
}

type userRecord struct{}

// Init
func (a *userRecord) Init(r *gin.RouterGroup) {
	g := r.Group("/userRecord", middleware.Auth())
	{
		g.POST("/create", a.create)
		g.POST("/update", a.update)
		g.POST("/list", a.list)
		g.POST("/delete", a.delete)
		g.POST("/detail", a.find)
		g.POST("/login", a.login)
	}
}

// create
func (a *userRecord) create(c *gin.Context) {
	var (
		in  = &model.UserRecordCreateRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 获取用户ID
	userId, err := request.GetUserId(c.Request.Context())
	if err != nil {
		c.Error(err)
		return
	}
	in.UserId = userId

	if err = bll.UserRecord.Create(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, nil)
}

// update
func (a *userRecord) update(c *gin.Context) {
	var (
		in  = &model.UserRecordUpdateRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 获取用户ID
	if c.GetHeader("source") != "web" {
		userId, err := request.GetUserId(c.Request.Context())
		if err != nil {
			c.Error(err)
			return
		}
		in.UserId = &userId
	}

	if err = bll.UserRecord.Update(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, nil)
}

// list
func (a *userRecord) list(c *gin.Context) {
	var (
		in   = &model.UserRecordListRequest{}
		resp = &po.UserRecordListResponse{}
		err  error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	var out = &model.UserRecordListResponse{}
	if out, err = bll.UserRecord.List(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}

	if len(out.List) <= 0 {
		utils.ResponseOkWithError(c, "没有找到相关记录！！！")
		return
	}

	// 加载用户昵称和头像
	var userIds []string
	for i := 0; i < len(out.List); i++ {
		userIds = append(userIds, out.List[i].UserId)
	}

	// 结果
	result, err := redis.KV.HMGet(c.Request.Context(), "quanxi:user_info", userIds...).Result()
	if err != nil {
		c.Error(err)
		return
	}

	userDataMap := make(map[string]*request.UserData)
	for i := 0; i < len(result); i++ {
		userData := &request.UserData{}
		if result[i] == nil {
			continue
		}

		_ = json.Unmarshal([]byte(result[i].(string)), userData)
		if userData.Unionid != "" {
			userDataMap[userData.Unionid] = userData
		}
	}

	for i := 0; i < len(out.List); i++ {
		if v, ok := userDataMap[out.List[i].UserId]; ok {
			out.List[i].NickName = v.UserName
			out.List[i].Avatar = v.AvatarUrl
		}
	}

	var supervisorIds []string
	for i := 0; i < len(out.List); i++ {
		if out.List[i].Supervisor > 0 {
			supervisorIds = append(supervisorIds, out.List[i].UserId)
		}
	}

	resp.Total = out.Total
	respDataMap := make(map[string]*po.UserRecordInfo)
	for i := 0; i < len(out.List); i++ {
		respDataMap[out.List[i].UserId] = &po.UserRecordInfo{
			UserRecordInfo: *out.List[i],
			WithDrawData:   po.WithDrawData{},
			UserMoney:      out.List[i].UserMoney,
			WithdrawMoney:  out.List[i].WithdrawMoney,
		}
		resp.List = append(resp.List, respDataMap[out.List[i].UserId])

	}

	// 处理提现记录
	if len(supervisorIds) > 0 {
		// 统计待提现订单数量，统计总金额
		status := 0
		list, _ := bll.SupervisorOrder.List(c.Request.Context(), &model.SupervisorOrderListRequest{
			SupervisorIds: supervisorIds,
			Status:        &status,
			Index:         1,
			Size:          10000,
		})
		nowUnix := time.Now().Unix()
		for i := 0; i < len(list.List); i++ {
			if v, ok := respDataMap[list.List[i].SupervisorId]; ok {
				v.WithDrawData.TotalAmount += list.List[i].Price
				v.WithDrawData.DeductAmount += list.List[i].DeductCount
				if nowUnix-list.List[i].CreatedAt < 7*24*3600 {
					v.WithDrawData.FrozenAmount += list.List[i].Price
					v.WithDrawData.FrozenDeduct += list.List[i].DeductCount
				}
				v.WithDrawData.OrderCount++
			}
		}

	}

	utils.ResponseOk(c, resp)
}

// list
func (a *userRecord) find(c *gin.Context) {
	var (
		in  = &model.UserRecordInfoRequest{}
		out = &model.UserRecordInfo{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 获取用户ID
	if c.GetHeader("source") != "web" {
		userId, err := request.GetUserId(c.Request.Context())
		if err != nil {
			c.Error(err)
			return
		}
		in.UserId = userId
	}

	if out, err = bll.UserRecord.Find(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, out)
}

// delete
func (a *userRecord) delete(c *gin.Context) {
	var (
		in  = &model.UserRecordDeleteRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if err = bll.UserRecord.Delete(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, nil)
}

// login
func (a *userRecord) login(c *gin.Context) {
	var (
		in  = &po.UserLoginReq{}
		err error
	)

	defer func() {
		defer utils.ExceptionCatch()
		userData, err := request.GetUserData(c.Request.Context())
		if err != nil {
			return
		}

		if userData.UserName != "" {
			_ = bll.UserRecord.Update(c.Request.Context(), &model.UserRecordUpdateRequest{
				UserId:      &in.UserId,
				NickName:    &userData.UserName,
				Avatar:      &userData.AvatarUrl,
				WxwebOpenid: &userData.WxwebOpenid,
			})
		}

		redis.KV.HSet(c.Request.Context(), "quanxi:user_info", in.UserId, utils.ToJsonString(userData))
		log.Info("###### 用户信息更新 ", zap.Any("userId:", in.UserId))
	}()

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 获取用户ID
	if in.UserId == "" {
		userId, err := request.GetUserId(c.Request.Context())
		if err != nil {
			c.Error(err)
			return
		}
		in.UserId = userId
	}

	token := c.GetHeader("Authorization")
	log.Info("############## 用户登录了 ", zap.Any("userId", in.UserId), zap.Any("token", token), zap.Any("data", utils.ToJsonString(in)))

	go func() {
		defer utils.ExceptionCatch()
		bll.UserLogin(c.Request.Context(), in.UserId)
	}()

	var out = &po.UserLoginRsp{
		UserId: in.UserId,
	}

	var errGroup errgroup.Group

	// 训练数据
	errGroup.Go(func() error {
		list, _ := bll.AiConsult.List(c.Request.Context(), &model.AiConsultListRequest{
			UserId: &in.UserId,
			Index:  1,
			Size:   10000,
		})

		trainMap := make(map[int]*po.TrainData)
		for i := 0; i < len(list.List); i++ {
			if _, ok := trainMap[list.List[i].Level]; !ok {
				trainMap[list.List[i].Level] = &po.TrainData{
					TrainLevel: list.List[i].Level,
				}
				out.UserTrainList = append(out.UserTrainList, trainMap[list.List[i].Level])
			}

			trainMap[list.List[i].Level].TrainCount += 1
		}
		return nil
	})

	// 处理提现记录
	if in.Supervisor == 1 {
		errGroup.Go(func() error {
			// 统计待提现订单数量，统计总金额
			status := 0
			list, _ := bll.SupervisorOrder.List(c.Request.Context(), &model.SupervisorOrderListRequest{
				SupervisorId: &in.UserId,
				Status:       &status,
				Index:        1,
				Size:         10000,
			})
			nowUnix := time.Now().Unix()
			for i := 0; i < len(list.List); i++ {
				out.WithDrawData.TotalAmount += list.List[i].Price
				out.WithDrawData.DeductAmount += list.List[i].DeductCount
				if nowUnix-list.List[i].CreatedAt < 7*24*3600 {
					out.WithDrawData.FrozenAmount += list.List[i].Price
					out.WithDrawData.FrozenDeduct += list.List[i].DeductCount
				}
			}

			out.WithDrawData.OrderCount = list.Total
			return nil
		})
	}

Retry:
	// 查询用户记录是否存在
	find, err := bll.UserRecord.Find(c.Request.Context(), &model.UserRecordInfoRequest{
		UserId: in.UserId,
	})

	if err != nil {
		// 不存在进行创建
		if err == gorm.ErrRecordNotFound {
			if err = bll.UserRecord.Create(c.Request.Context(), &model.UserRecordCreateRequest{
				UserId:    in.UserId,
				UnlockNum: 1,
			}); err != nil {
				c.Error(err)
				return
			}

			goto Retry
		} else {
			c.Error(err)
		}
		return
	} else {
		out.Supervisor = find.Supervisor
		out.CreatedAt = find.CreatedAt
		out.CustomData = find.CustomData
		out.UserMoney = find.UserMoney
		out.WithdrawMoney = find.WithdrawMoney
		out.UnlockNum = GetUnlockNum(find.CreatedAt)
	}

	errGroup.Wait()
	// 督导师
	if in.LoginType == 1 {
		if in.Supervisor == 1 {
			// 督导师上线
			if find.Supervisor == in.Supervisor {
				utils.ResponseOk(c, out)
				return
			}
			c.Error(fmt.Errorf("你没有权限登录督导师账号！"))
			return
		}
		utils.ResponseOk(c, out)
		return
	} else {
		// 检查vip
		token := c.GetHeader("Authorization")
		bVip, err := request.CheckUserVipStatus(token, config.Conf.Env)
		log.Info(err.Error())
		if !bVip {
			c.Error(fmt.Errorf("您当前不是VIP，请充值后再来！"))
			return
		}
	}

	utils.ResponseOk(c, out)
}

func GetUnlockNum(createTime int64) int {
	nowUnix := time.Now().Unix()
	return SpanDayNumber(createTime, nowUnix) + 1
}

// SpanDayNumber 获取两个时间戳跨度的天数
func SpanDayNumber(unix, endUnix int64) int {
	t1 := time.Unix(unix, 0)
	t2 := time.Unix(endUnix, 0)

	t1 = time.Date(t1.Year(), t1.Month(), t1.Day(), 0, 0, 0, 0, time.Local)
	t2 = time.Date(t2.Year(), t2.Month(), t2.Day(), 0, 0, 0, 0, time.Local)

	return int(t2.Sub(t1).Hours() / 24)
}
